module ShiftDivider(
    input           clock,
    input           reset,
    input  [63:0]   x,
    input  [63:0]   y,
    input           sign,
    input           word,
    input           valid,
    output          ready,
    output [63:0]   q,
    output [63:0]   r,
    output          done
);

    reg [127:0] X;
    reg [ 63:0] Y;
    reg [ 63:0] Q;
    reg [ 63:0] R;

    reg sign_R, word_R;
    reg msb_x_R, msb_y_R;

    localparam IDLE = 3'b001, CALC = 3'b010, DONE = 3'b100;

    reg [2:0] state;
    reg [7:0] count;

    assign ready = (state == IDLE);
    assign done  = (state == DONE);

    always @(posedge clock) begin
        if (reset) begin
            state   <= IDLE;
            count   <= 0;
            { X, Y, Q, R }          <= 0;
            { sign_R, word_R }      <= 0;
            { msb_x_R, msb_y_R }    <= 0;
        end
        else begin
            case (state) 
                IDLE: begin
                    // 准备计算
                    if (valid & ready) begin
                        state <= CALC;
                        count <= word ? 32 : 64;
                        X <= X_init;
                        Y <= Y_init;
                        Q <= 0;
                        R <= 0;
                        sign_R <= sign;
                        word_R <= word;
                        msb_x_R <= word ? x[31] : x[63];
                        msb_y_R <= word ? y[31] : y[63];
                    end
                end
                CALC: begin
                    // 继续计算
                    if (|count) begin
                        state <= CALC;
                        count <= count - 1;
                        if (delta_sign) begin
                            Q <= Q_next_0;
                            R <= R_next_0;
                            X <= X_next_0;
                        end
                        else begin
                            Q <= Q_next_1;
                            R <= R_next_1;
                            X <= X_next_1;
                        end
                    end
                    // 结束计算
                    else begin
                        state   <= DONE;
                        count   <= 0;
                    end
                end
                // 完成计算
                DONE: begin
                    state <= IDLE;
                end
                default: begin
                    state   <= IDLE;
                end
            endcase
        end
    end

    wire [64:0] delta_op1 = ({65{ word_R}} & {32'h0, X[ 63 -: 33]})  // 32 bit
                          | ({65{~word_R}} & {       X[127 -: 65]}); // 64 bit
    wire [64:0] delta_op2 = ({65{ word_R}} & {33'h0, Y[31:0]})  // 32 bit
                          | ({65{~word_R}} & { 1'b0, Y[63:0]}); // 64 bit

    wire [64:0] delta = delta_op1 - delta_op2;
    wire delta_sign = word_R ? delta[32] : delta[64];

    wire [ 63:0] Q_next_0   = ({64{ word_R}} & {32'h0, Q[30:0], 1'b0})      // 32 bit
                            | ({64{~word_R}} & {       Q[62:0], 1'b0});     // 64 bit
    wire [ 63:0] R_next_0   = ({64{ word_R}} & {32'h0, X[ 62 -: 32]})       // 32 bit
                            | ({64{~word_R}} & {       X[126 -: 64]});      // 64 bit
    wire [127:0] X_next_0   = ({128{ word_R}} & {64'h0, X[ 62:0], 1'b0})    // 32 bit
                            | ({128{~word_R}} & {       X[126:0], 1'b0});   // 64 bit
    
    wire [ 63:0] Q_next_1   = ({64{ word_R}} & {32'h0, Q[30:0], 1'b1})      // 32 bit
                            | ({64{~word_R}} & {       Q[62:0], 1'b1});     // 64 bit
    wire [ 63:0] R_next_1   = ({64{ word_R}} & {32'h0, delta[31:0]})        // 32 bit
                            | ({64{~word_R}} & {       delta[63:0]});       // 64 bit
    wire [127:0] X_next_1   = ({128{ word_R}} & {64'h0, delta[31:0], X[30:0], 1'b0})  // 32 bit
                            | ({128{~word_R}} & {       delta[63:0], X[62:0], 1'b0}); // 64 bit

    wire [ 63:0] neg_x = ~x + 1;
    wire [ 63:0] neg_y = ~y + 1;

    wire [127:0] X_init = ({128{ word}} & {96'h0, (sign & x[31]) ? neg_x[31:0] : x[31:0]})  // 32 bit
                        | ({128{~word}} & {64'h0, (sign & x[63]) ? neg_x[63:0] : x[63:0]}); // 64 bit
    wire [ 63:0] Y_init = ({ 64{ word}} & {32'h0, (sign & y[31]) ? neg_y[31:0] : y[31:0]})  // 32 bit
                        | ({ 64{~word}} & {       (sign & y[63]) ? neg_y[63:0] : y[63:0]}); // 64 bit

    wire [63:0] neg_Q = ~Q + 1;
    wire [63:0] neg_R = ~(R - 1);

    wire [63:0] q64 = (sign_R & (msb_x_R ^ msb_y_R)) ? neg_Q : Q;
    wire [63:0] r64 = (sign_R & msb_x_R) ? neg_R : R;

    assign q = word_R ? {32'h0, q64[31:0]} : q64[63:0];
    assign r = word_R ? {32'h0, r64[31:0]} : r64[63:0];

endmodule
